﻿using Engine.Graphics;
using Engine.Graphics.Shaders;
using Engine.Graphics.VertexStructures;
using SharpDX;
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.IO;
using System.Xml;

namespace Cobra11Undercover
{
    [ExportMetadata("Name", "C11 Undercover")]
    [ExportMetadata("Version", 1)]
    [Export(typeof(Engine.AddinManager.IAddin))]
    public class GameDll : Engine.AddinManager.IAddin
    {
        #region Internal Fields

        internal static readonly string gameName = "C11 Undercover";

        internal static C11UndercoverShaderArray shaderArray;

        #endregion Internal Fields

        #region Private Fields

        private Engine.Engine engine;

        #endregion Private Fields

        #region Public Constructors

        [ImportingConstructor]
        public GameDll([Import("MainEngine")]Engine.Engine engine)
        {
            this.engine = engine;

            // Load Shaderarray
            shaderArray = new C11UndercoverShaderArray(this.engine, ".\\Shaders\\", engine.Grafic.ShaderManager);
            SyneticStandards.StandardTest test = new SyneticStandards.StandardTest();
        }

        #endregion Public Constructors

        #region Public Properties

        public Engine.Graphics.IShaderArray ShaderArray
        {
            get
            {
                return shaderArray;
            }
        }

        #endregion Public Properties

        #region Public Methods

        public IMaterial CreateEmptyMaterial(MaterialManager materialManager)
        {
            Random rand = new Random((int)DateTime.Now.Ticks);

            int random = rand.Next(0, materialManager.TextureNames.Count - 1);
            int random2 = rand.Next(0, materialManager.TextureNames.Count - 1);
            int random3 = rand.Next(0, materialManager.TextureNames.Count - 1);
            return new Cobra11Undercover.Material.C11Material(random, random2, random3, EnumMappingMode.material32, materialManager);
        }

        public IGameVertex CreateGameVertice(MyOwnVertex.PositionNormalTextured vertex)
        {
            return new C11UCVertex.C11UCData()
            {
                UV = new SharpDX.Vector3(vertex.UV.X, vertex.UV.Y, 0),
                UV2 = new SharpDX.Vector4(vertex.UV.X, vertex.UV.Y, 0, 0),
                DiffuseColor = new SharpDX.Color4
                {
                    Alpha = 1.0f,
                    Red = 0.4f,
                    Green = 0.4f,
                    Blue = 0.4f
                },
                VertexColor = new SharpDX.Color4
                {
                    Alpha = 1.0f,
                    Red = 1.0f,
                    Green = 1.0f,
                    Blue = 1.0f
                },
            };
        }

        public string GetGameName()
        {
            return gameName;
        }

        public int GetSizeOfVertex()
        {
            return C11UCVertex.C11UCData.SizeInBytes();
        }

        public IMaterial LoadMaterial(BinaryReader br, MaterialManager materialManager)
        {
            throw new NotImplementedException();
        }

        public IMaterial LoadMaterialXml(XmlTextReader reader, MaterialManager materialManager)
        {
            return Cobra11Undercover.Material.C11Material.FromXmlStream(reader, materialManager);
        }

        public List<IGameVertex> LoadVerticesFromStream(int numberOfVertices, BinaryReader vertexReader, int BlockSize, int vertexVersion)
        {
            return LoadVerticesFromStream(null, numberOfVertices, vertexReader, BlockSize, vertexVersion);
        }

        public List<IGameVertex> LoadVerticesFromStream(List<Engine.Graphics.VertexStructures.MyOwnVertex.PositionNormalTextured> engineVertices,
            int numberOfVertices, BinaryReader vertexReader, int BlockSize, int vertexVersion)
        {
            List<IGameVertex> gameVertices = new List<IGameVertex>();

            // Read game vertices
            for (int v = 0; v < numberOfVertices; v++)
            {
                C11UCVertex.C11UCData vertexWr2Data = C11UCVertex.C11UCData.FromStream(vertexReader, vertexVersion);

                // TODO: Create a option in Modelimporter app to change these data there. (Shadow and diffuse color);

                vertexWr2Data.VertexColor = new Color4()
                {
                    Alpha = 0.0f,// Clear WR2 Shadow
                    Red = vertexWr2Data.VertexColor.Red,
                    Green = vertexWr2Data.VertexColor.Green,
                    Blue = vertexWr2Data.VertexColor.Blue
                };
                vertexWr2Data.DiffuseColor = new Color4()
                {
                    Alpha = 1.0f,
                    Red = 0.4f,
                    Green = 0.4f,
                    Blue = 0.4f
                };

                gameVertices.Add(vertexWr2Data);
            }

            if (engineVertices == null)
            {
                return gameVertices;
            }
            else
            {
                if (engineVertices.Count != numberOfVertices)
                    throw new System.Exception("Number of engine vertices doesn´t match number of gamevertices.");

                for (int i = 0; i < engineVertices.Count; i++)
                {
                    C11UCVertex.C11UCData tempVertex = (C11UCVertex.C11UCData)gameVertices[i];
                    tempVertex.Tu = engineVertices[i].UV.X;
                    tempVertex.Tv = engineVertices[i].UV.Y;
                    gameVertices[i] = tempVertex;
                }

                return gameVertices;
            }
        }

        public void UpdateVertexBuffer(StandardGraphicBuffers standardGraphicBuffers, IGameVertex[] vertices)
        {
            C11UCVertex.C11UCData[] data = new C11UCVertex.C11UCData[vertices.Length];

            for (int i = 0; i < vertices.Length; i++)
            {
                data[i] = (C11UCVertex.C11UCData)vertices[i];
            }

            standardGraphicBuffers.UpdateVertexBufferGameData<C11UCVertex.C11UCData>(data);
        }

        #endregion Public Methods
    }
}